package com.csl.jsonpreference.configdes

import android.text.TextUtils
import com.csl.jsonpreference.bean.ConfigTYPE
import com.csl.jsonpreference.tag.JsonConfig
import com.csl.jsonpreference.util.CLog
import org.json.JSONArray
import org.json.JSONObject

/**
 * json object类型
 */
open class JsonObjectPreference : JsonConfigIns {

    /** 数据描述*/
    var paramDesMap: HashMap<String, JsonConfigIns> = HashMap()

    /** 当前所在级别的jsonObject*/
    var jsonData: JSONObject

    /** 指定解析的class对象*/
    var classType: Class<*>? = null

    override fun getParseValueStr(): String {
//            CLog.d("jsonvalue", "替换值: $field")
        if (valueStr.contains("&")) {
            CLog.d("jsonvalue", "替换前: $valueStr")
            var result = valueStr
            //做字符替换
            for (k in paramDesMap.keys) {
                CLog.d("jsonvalue", "替换 &$k -> : ${jsonData.optString(k, "")}")
                result = result.replace("&$k", jsonData.optString(k, ""))
            }
            CLog.d("jsonvalue", "替换后: $result")
            return result
        } else {
            return valueStr
        }
    }


    constructor(
        jsonData: JSONObject,
        classType: Class<*>? = null,
        replaceConfig: JsonConfigIns? = null,
    ) : super(replaceConfig ?: JsonConfigIns("", "", "", ConfigTYPE.OBJECT)) {
        paramDesMap.clear()
        this.jsonData = jsonData
        this.classType = classType
        if (configType == ConfigTYPE.AUTO || configType == ConfigTYPE.OBJECT) {
            autoSetType(jsonData, classType, replaceConfig)
            configType = ConfigTYPE.OBJECT
        }
        CLog.d("initjson", "jsongroup 替换信息: $replaceConfig")
        CLog.d("initjson", "jsongroup 信息:" + this)
    }

    /**
     * 自动判断类型
     *
     */
    fun autoSetType(
        jsonData: JSONObject,
        classType: Class<*>? = null,
        jsonConfig: JsonConfigIns?
    ) {
        //先遍历属性配置表
//        val fields = classType?.fields ?: emptyArray() //静态属性
        val fields = classType?.declaredFields ?: emptyArray()
        for (field in fields) {
            //不需要反射属性
//            field.isAccessible = true
            CLog.d("initjson", "遍历字段: ${field.name}, ${field.type}")
            //在父类作为属性时的配置
            var fieldJsonConfig =
                JsonConfigIns(field.getAnnotation(JsonConfig::class.java) ?: continue)
            var fieldJsonData: JSONObject? = null
            var fieldClass = field.type

            val jsonkey =
                if (TextUtils.isEmpty(fieldJsonConfig.key)) field.name else fieldJsonConfig.key
            fieldJsonConfig.key = jsonkey

            CLog.d("initjson", "注解信息:" + fieldJsonConfig)

            //识别类型
            if (fieldJsonConfig.configType == ConfigTYPE.AUTO) {
                field.type.getAnnotation(JsonConfig::class.java)?.let { fieldTypeConfig ->
                    CLog.d("initjson", "类型自带信息:" + fieldTypeConfig)
                    //子类自己的config
                    //使用属性的jsonConfig覆盖类
                    fieldJsonConfig.configType = ConfigTYPE.OBJECT
                    fieldJsonConfig.replaceDefaultConfig(
                        fieldTypeConfig
                    ).apply {
                        this.configType = ConfigTYPE.OBJECT
                    }
                    fieldJsonData = jsonData?.optJSONObject(fieldJsonConfig.key)
                }
            }
            CLog.d("initjson", "替换后的注解信息:" + fieldJsonConfig)
            //根据类型创建
            when (fieldJsonConfig.configType) {
                ConfigTYPE.OBJECT -> {
                    //object类型
                    var jsonObj = jsonData.optJSONObject(fieldJsonConfig.key)
                    if (jsonObj == null) {
                        jsonObj = JSONObject()
                        jsonData.put(fieldJsonConfig.key, jsonObj)
                    }
                    paramDesMap.put(
                        fieldJsonConfig.key,
                        JsonObjectPreference(
                            jsonObj,
                            field.type,
                            fieldJsonConfig
                        )
                    )
                    CLog.d("initjson", "添加注解信息:" + paramDesMap.get(fieldJsonConfig.key))
                }
//                ConfigTYPE.ARRAY_BOOLEAN,
//                ConfigTYPE.ARRAY_NUMBER,
//                ConfigTYPE.ARRAY_TXT,
//                ConfigTYPE.ARRAY_FLOAT,
                ConfigTYPE.ARRAY_OBJECT -> {
                    var jsonObj = jsonData?.optJSONArray(fieldJsonConfig.key)
                    if (jsonObj == null) {
                        jsonObj = JSONArray()
                        jsonData?.put(fieldJsonConfig.key, jsonObj)
                    }
                    val arrayPreference = JsonArrayPreference(
                        jsonObj, fieldClass, fieldJsonConfig
                    )
                    paramDesMap.put(jsonkey, arrayPreference)
                }

//                ConfigTYPE.TXT,
//                ConfigTYPE.FLOAT,
//                ConfigTYPE.NUMBER,
//                ConfigTYPE.BOOLEAN,
//                ConfigTYPE.AUTO,
                else -> {
                    if (fieldJsonConfig.isArrayType(fieldClass)) {
                        var jsonObj = jsonData.optJSONArray(fieldJsonConfig.key)
                        if (jsonObj == null) {
                            jsonObj = JSONArray()
                            jsonData.put(fieldJsonConfig.key, jsonObj)
                        }
                        paramDesMap.put(
                            jsonkey, JsonArrayPreference(
                                jsonObj,
                                fieldClass,
                                fieldJsonConfig
                            )
                        )
                    } else {
                        //普通模式都走基础类型解析
                        paramDesMap.put(
                            jsonkey, JsonBasePreference(
                                jsonData,
                                fieldClass,
                                fieldJsonConfig
                            )
                        )
                    }
                }
            }

        }
        //json里存在, 配置表不存在时
        jsonData?.let {
            var jsonKeys = it.keys()
            for (jsonKey in jsonKeys) {
                CLog.d("initjson", "遍历json内字段: ${jsonKey}")
                if (!paramDesMap.containsKey(jsonKey)) {
                    //配置表没有, 默认作为字符串类型
                    var value = it.get(jsonKey)
                    CLog.d("initjson", "判断json字段类型: ${jsonKey}: ${value.javaClass.name}")

                    when (value.javaClass) {
                        JSONObject::class.java -> {
                            var jsonObj = it.optJSONObject(jsonKey)
                            if (jsonObj == null) {
                                jsonObj = JSONObject()
                                it.put(jsonKey, jsonObj)
                            }
                            val objPreference = JsonObjectPreference(
                                jsonObj,
                                null,
                                JsonConfigIns(
                                    jsonKey,
                                    jsonKey,
                                    "",
                                    ConfigTYPE.OBJECT
                                )
                            )
                            objPreference.jsonData = it.optJSONObject(jsonKey)
                            paramDesMap.put(jsonKey, objPreference)
                        }

                        JSONArray::class.java -> {
                            var jsonObj = it.optJSONArray(jsonKey)
                            if (jsonObj == null) {
                                jsonObj = JSONArray()
                                it.put(jsonKey, jsonObj)
                            }
                            val objPreference = JsonArrayPreference(
                                jsonObj,
                                null,
                                JsonConfigIns(
                                    jsonKey,
                                    jsonKey,
                                    "",
                                    ConfigTYPE.ARRAY_OBJECT
                                )
                            )
                            objPreference.jsonData = it.optJSONArray(jsonKey)
                            paramDesMap.put(jsonKey, objPreference)

                        }

                        Double::class.java, java.lang.Double::class.java -> {
                            val objPreference = JsonBasePreference(
                                it.optJSONObject(jsonKey),
                                null,
                                JsonConfigIns(
                                    jsonKey,
                                    jsonKey,
                                    "",
                                    ConfigTYPE.FLOAT
                                )
                            )
                            paramDesMap.put(jsonKey, objPreference)
                        }

                        Int::class.java, Integer::class.java, Long::class.java, java.lang.Long::class.java -> {
                            val objPreference = JsonBasePreference(
                                it.optJSONObject(jsonKey),
                                null,
                                JsonConfigIns(
                                    jsonKey,
                                    jsonKey,
                                    "",
                                    ConfigTYPE.NUMBER
                                )
                            )
                            paramDesMap.put(jsonKey, objPreference)
                        }

                        Boolean::class.java, java.lang.Boolean::class.java -> {
                            val objPreference = JsonBasePreference(
                                it.optJSONObject(jsonKey),
                                null,
                                JsonConfigIns(
                                    jsonKey,
                                    jsonKey,
                                    "",
                                    ConfigTYPE.BOOLEAN
                                )
                            )
                            paramDesMap.put(jsonKey, objPreference)
                        }
//                        String::class.java, java.lang.String::class.java -> {
//
//                        }
                        else -> {
                            CLog.d(
                                "initjson",
                                "新增json默认字段 文本: ${jsonKey}:${it.optString(jsonKey)}"
                            )

                            val objPreference = JsonBasePreference(
                                it.optJSONObject(jsonKey),
                                null,
                                JsonConfigIns(
                                    jsonKey,
                                    jsonKey,
                                    "",
                                    ConfigTYPE.TXT
                                )
                            )
                            paramDesMap.put(jsonKey, objPreference)
                        }
                    }
                }
            }
        }

    }

    fun getParamsList(): ArrayList<JsonConfigIns> {
        var result = ArrayList<JsonConfigIns>()
        result.addAll(paramDesMap.values)
        result.sortBy {
            it.index
        }
        return result
    }
}